﻿using System;

namespace BTSegWay
{
    /// <summary>
    /// Container object for data values and from DIYS
    /// </summary>
    public class DIYSValues
    {

        public struct Profiles
        {
            public double KP { get; set; }
            public double KD { get; set; }
            public double KS { get; set; }
        }

        #region parameters
        private readonly Profiles _beginnerProfile = new Profiles { KP = 20, KD = 1.5, KS = 1.5 };
        private readonly Profiles _normalProfile = new Profiles { KP = 30, KD = 1.5, KS = 1.5 };
        private readonly Profiles _extremeProfile = new Profiles { KP = 46, KD = 1.5, KS = 2 };
        #endregion


        #region private members
        private double _kp, _kd, _ks = 0;
        private double _accAngle, _gyroAnglePrSec, _approxAngle = 0;
        private int _pwm, _steering = 0;
        private Profiles _activeProfile;
        #endregion

        #region events
        
        /// <summary>
        /// Occurs when KP value is changed
        /// </summary>
        public event DoubleDelegate OnKPChanged;

        /// <summary>
        /// Occurs when KD value is changed
        /// </summary>
        public event DoubleDelegate OnKDChanged;
        
        /// <summary>
        /// Occurs when KS value is changed
        /// </summary>
        public event DoubleDelegate OnKSChanged;

        /// <summary>
        /// Occurs when Accelerometer Angle value is changed
        /// </summary>
        public event DoubleDelegate OnAccAngleChanged;

        /// <summary>
        /// Occurs when Gyro value is changed
        /// </summary>
        public event DoubleDelegate OnGyroAngleChanged;
        
        /// <summary>
        /// Occurs when Approximated Angle is changed
        /// </summary>
        public event DoubleDelegate OnApproxAngleChanged;

        /// <summary>
        /// Occurs when PWM value is changed
        /// </summary>
        public event IntegerDelegate OnPWMChanged;
        
        /// <summary>
        /// Occurs when Steering value is changed
        /// </summary>
        public event IntegerDelegate OnSteeringChanged;
        #endregion

        #region properties
        public Profiles Beginner { get { return _beginnerProfile; } }
        public Profiles Normal { get { return _normalProfile; } }
        public Profiles Extreme { get { return _extremeProfile; } }


        public Profiles ActiveProfile 
        {
            get { return _activeProfile; }
            set 
            {
                if (!_activeProfile.Equals(value))
                {
                    _activeProfile = value;
                    KP = _activeProfile.KP;
                    KD = _activeProfile.KD;
                    KS = _activeProfile.KS;
                }            
            }
        }

        /// <summary>
        /// Gets or sets KP value. Fires event when changed
        /// </summary>
        public double KP
        {
            get { return _kp; }
            set
            {
                if (value <= 50 && value >= 0)
                    _kp = Math.Round(value, 2);
                if (OnKPChanged != null)
                    OnKPChanged(_kp);

            }
        }

        /// <summary>
        /// Gets or sets KD value. Fires event when changed
        /// </summary>
        public double KD
        {
            get { return _kd; }
            set
            {
                if (value <= 5 && value >= 0)
                    _kd = Math.Round(value, 2);
                if (OnKDChanged != null)
                    OnKDChanged(_kd);

            }
        }

        /// <summary>
        /// Gets or sets KS value. Fires event when changed
        /// </summary>
        public double KS
        {
            get { return _ks; }
            set
            {
                if (value <= 6 && value >= 0)
                    _ks = Math.Round(value, 2);
                if (OnKSChanged != null)
                    OnKSChanged(_ks);

            }
        }

        /// <summary>
        /// Gets or sets Accelerometer Angle value. Fires event when changed
        /// </summary>
        public double AccAngle
        {
            get { return _accAngle; }
            set
            {
                _accAngle = value;
                if (OnAccAngleChanged != null)
                    OnAccAngleChanged(_accAngle);
            }
        }

        /// <summary>
        /// Gets or sets Gyro Angle Pr Sec value. Fires event when changed
        /// </summary>
        public double GyroAnglePrSec
        {
            get { return _gyroAnglePrSec; }
            set
            {
                _gyroAnglePrSec = value;
                if (OnGyroAngleChanged != null)
                    OnGyroAngleChanged(_gyroAnglePrSec);
            }
        }

        /// <summary>
        /// Gets or sets Approximated Angle value. Fires event when changed
        /// </summary>
        public double ApproxAngle
        {
            get { return _approxAngle; }
            set
            {
                _approxAngle = value;
                if (OnApproxAngleChanged != null)
                    OnApproxAngleChanged(_approxAngle);
            }
        }

        /// <summary>
        /// Gets or sets PWM value. Fires event when changed
        /// </summary>
        public int PWM
        {
            get { return _pwm; }
            set
            {
                _pwm = value;
                if (OnPWMChanged != null)
                    OnPWMChanged(_pwm);
            }
        }

        /// <summary>
        /// Gets or sets Steering value. Fires event when changed
        /// </summary>
        public int Steering
        {
            get { return _steering; }
            set
            {
                _steering = value;
                if (OnSteeringChanged != null)
                    OnSteeringChanged(_steering);
            }
        }

        /// <summary>
        /// Gets or sets Whether log stream from diys is enable
        /// </summary>
        public bool StreamEnable { get; set; }

        #endregion
    }
}
